#include "../DWMRICore/Scalar.h"
#include "../DWMRICore/Point3I.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <vector>

char *pSrcPathname = NULL;
char *pDstPathname = NULL;

CScalar *pModelSelection;


void PrintUsage()
{
	printf("Usage: Segmentation -src src_file -dst dst_file\n");
}

int ParseArguments(const int argc, char *argv[])
{
	for (int i = 1; i < argc; ++i) {
		if (strcmp(argv[i], "-src") == 0) {
			pSrcPathname = argv[++i];
		} else if (strcmp(argv[i], "-dst") == 0) {
			pDstPathname = argv[++i];
		} else {
			return -1;
		}
	}

	if (pSrcPathname == NULL || pDstPathname == NULL)
		return -2;

	return 0;
}

void Segmentation()
{
	int w = pModelSelection->GetWidth();
	int h = pModelSelection->GetHeight();
	int d = pModelSelection->GetDepth();

	float *result = new float[w*h*d];
	int count = 0;
	while(true) {
		std::vector<CPoint3I> buffer;
		for (int z = 0; z < d; ++z) {
			for (int y = 0; y < h; ++y) {
				for (int x = 0; x < w; ++x) {
					if (pModelSelection->GetScalarFast(x, y, z) > 1.5f) {
						CPoint3I pos(x, y, z);
						buffer.push_back(pos);
						break;
					}
				}
				if (buffer.size() > 0)
					break;
			}
			if (buffer.size() > 0)
				break;
		}

		if (buffer.size() == 0)
			break;

		int temp_count = 1;
		while(buffer.size() > 0) {
			CPoint3I seed = buffer.back();
			buffer.pop_back();

			int min_z = seed.z-1 > 0 ? seed.z-1 : 0;
			int min_y = seed.y-1 > 0 ? seed.y-1 : 0;
			int min_x = seed.x-1 > 0 ? seed.x-1 : 0;
			int max_z = seed.z+1 < (d-1) ? seed.z+1 : d-1;
			int max_y = seed.y+1 < (h-1) ? seed.y+1 : h-1;
			int max_x = seed.x+1 < (w-1) ? seed.x+1 : w-1;

			for (int z = min_z; z <= max_z; ++z) {
				for (int y = min_y; y <= max_y; ++y) {
					for (int x = min_x; x <= max_x; ++x) {
						if (pModelSelection->GetScalarFast(x, y, z) > 1.5f) {
							CPoint3I pos(x, y, z);
							buffer.push_back(pos);
							pModelSelection->SetScalar(x, y, z, -(count+1));
							temp_count++;
						}
					}
				}
			}
		}

		count++;
	}

	printf("count = %d\n", count);
	for (int i = 0; i < count; ++i) {
		int size = 0;
		for (int j = 0; j < w *h*d; ++j) {
			if (fabs(pModelSelection->GetScalarFast(j) + float(i+1)) < 0.1f)
				size++;
		}
		if (size < 5000) {
			for (int j = 0; j < w *h*d; ++j) {
				if (fabs(pModelSelection->GetScalarFast(j) + float(i+1)) < 0.1f)
					pModelSelection->SetScalar(j, 1.0f);
			}
		}
		//printf("%d size  %d\n", i, size);
	}
	for (int j = 0; j < w *h*d; ++j) {
		if (pModelSelection->GetScalarFast(j) < -0.5f)
			pModelSelection->SetScalar(j, 2.0f);
	}


	SafeDeleteArray(result);
}

int main(int argc, char *argv[])
{
	if (ParseArguments(argc, argv) != 0) {
		PrintUsage();
		return 0;
	}

	pModelSelection = new CScalar();
	pModelSelection->OpenScalarFile(pSrcPathname);

	Segmentation();

	pModelSelection->SaveScalarFile(pDstPathname);

	SafeDelete(pModelSelection);

	return 0;
}